﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using LowLevelGraphics.Filter;
using LowLevelGraphics.Types;

namespace LowLevelGraphics.Analysis
{
    /// <summary>
    /// This will do a special analysis whie is PROCESSING_MODE dependant.
    /// Pixels will be sorted by some of their characteristics.
    /// Impressing is that this will deliver any region of pics that seem to be interesting.
    /// </summary>
    public class DrawPixelColorDependencyLine
    {
        private List<Point> aPointConnect = new List<Point>();

        private Bitmap m_Bitmap = null;
        private DIRECTION_MODE M_DIRECTION_MODE = DIRECTION_MODE.BOTH;
        private PROCESSING_MODE M_PROCESSING_MODE = PROCESSING_MODE.SumRGB;

        private int m_nWidth = -1;
        private int m_nHeight = -1;

        /// <summary>
        /// Initializes a new instance of the <see cref="DrawPixelColorDependencyLine"/> class.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        public DrawPixelColorDependencyLine(Bitmap _bitmap)
            : this(_bitmap, DIRECTION_MODE.HORIZONTAL, PROCESSING_MODE.SumRGB)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DrawPixelColorDependencyLine"/> class.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        /// <param name="_MODE">The _ MODE.</param>
        /// <param name="_PROCESSING_MODE">The _ PROCESSIN g_ MODE.</param>
        public DrawPixelColorDependencyLine(Bitmap _bitmap, DIRECTION_MODE _MODE, PROCESSING_MODE _PROCESSING_MODE)
        {
            m_Bitmap = _bitmap;
            M_DIRECTION_MODE = _MODE;
            M_PROCESSING_MODE = _PROCESSING_MODE;
            m_nHeight = _bitmap.Height;
            m_nWidth = _bitmap.Width;
        }

        /// <summary>
        /// This will always draw the lines...
        /// </summary>
        public void Analyse()
        {
            Analyse(true);
        }

        /// <summary>
        /// Analyses this instance.
        /// </summary>
        /// <param name="_bDrawLines">Choose whether to draw lines in pic or not</param>
        public void Analyse(bool _bDrawLines)
        {
            aPointConnect = new List<Point>();
            using (BitmapFunctions bitmapFunctions = new BitmapFunctions(m_Bitmap))
            {
                if (M_DIRECTION_MODE == DIRECTION_MODE.HORIZONTAL)
                {
                    Horizontal(aPointConnect, bitmapFunctions);
                }
                else if (M_DIRECTION_MODE == DIRECTION_MODE.VERTICAL)
                {
                    Vertical(aPointConnect, bitmapFunctions);
                }
                else
                {
                    Horizontal(aPointConnect, bitmapFunctions);
                    Vertical(aPointConnect, bitmapFunctions);
                }
            }

            if (_bDrawLines)
            {
                DrawLines();
            }
        }

        /// <summary>
        /// DrawLines
        /// </summary>
        private void DrawLines()
        {
            Graphics g = Graphics.FromImage((Bitmap)m_Bitmap);
            Point pt = aPointConnect[0];
            int i = 0;
            for (i = 1; i < aPointConnect.Count; i++)
            {
                g.DrawLine(Pens.Red, aPointConnect[i - 1], aPointConnect[i]);
            }
        }

        /// <summary>
        /// Verticals the specified _a point connect.
        /// </summary>
        /// <param name="_aPointConnect">The _a point connect.</param>
        /// <param name="_bitmapFunctions">The _bitmap functions.</param>
        private void Vertical(List<Point> _aPointConnect, BitmapFunctions _bitmapFunctions)
        {
            ColorCalculation colorCalculation = Definitions.ColorCalculationDictionaryProcessingMode[M_PROCESSING_MODE];

            UnsafeBitmap bitmapCloned = (Bitmap)m_Bitmap.Clone();
            float fValue = float.MaxValue;
            Color color = Color.Transparent;
            Color colorLast = Color.Transparent;
            int x = 0;
            for (x = 0; x < m_nWidth; x++)
            {
                ColorPixel<int> aPoint = new ColorPixel<int>(colorLast, (int)fValue);
                float fLimit = float.MaxValue;
                Point ptLast = Point.Empty;
                for (int y = 0; y < m_nHeight; y++)
                {
                    color = bitmapCloned.GetPixel(x, y);
                    fValue = colorCalculation(color);
                    if (fValue < fLimit)
                    {
                        colorLast = color;
                        fLimit = fValue;
                        aPoint.Point = new Point(x, y);
                        aPoint.Color = colorLast;
                    }
                }
                _aPointConnect.Add(aPoint.Point);
            }
        }

        /// <summary>
        /// Return Connection Points
        /// </summary>
        public List<Point> ConnectionPoints
        {
            get { return aPointConnect; }
        }

        /// <summary>
        /// Horizontals the specified _a point connect.
        /// </summary>
        /// <param name="_aPointConnect">The _a point connect.</param>
        /// <param name="_bitmapFunctions">The _bitmap functions.</param>
        private void Horizontal(List<Point> _aPointConnect, BitmapFunctions _bitmapFunctions)
        {
            ColorCalculation colorCalculation = Definitions.ColorCalculationDictionaryProcessingMode[M_PROCESSING_MODE];

            UnsafeBitmap bitmapCloned = (Bitmap)m_Bitmap.Clone();

            float fValue = float.MaxValue;
            Color color = Color.Transparent;
            Color colorLast = Color.Transparent;
            int y = 0;
            for (y = 0; y < m_nHeight; y++)
            {
                ColorPixel<int> aPoint = new ColorPixel<int>(colorLast, (int)fValue);
                //Array.Sort(aPoint, new ColorPixelSorter<int>(M_PROCESSING_MODE));
                float fLimit = float.MaxValue;
                Point ptLast = Point.Empty;
                for (int x = 0; x < m_nWidth; x++)
                {
                    color = bitmapCloned.GetPixel(x, y);
                    fValue = colorCalculation(color);
                    if (fValue < fLimit)
                    {
                        colorLast = color;
                        fLimit = fValue;
                        aPoint.Point = new Point(x, y);
                        aPoint.Color = colorLast;
                    }
                }
                _aPointConnect.Add(aPoint.Point);
            }
        }
    }
}
